<template>
  <div class="hotel w">
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item>酒店</el-breadcrumb-item>
      <el-breadcrumb-item>{{ $store.state.hotel.locationCity }}酒店预订</el-breadcrumb-item>
    </el-breadcrumb>
    <HotelSearchForm
      :api="{ getCities }"
      @search-hotel="handleSearchHotel"
    />
    <HotelAreaInfo
      @location="handleLocation"
      :scenics="cityInfo.scenics"
      :hotelInfos="hotelInfos"
    />
    <HotelInfoFilter @filter-hotel-info="renderHotelDetails(searchData)" />
    <HotelList
      :hotels="hotelInfos"
      @pagination-change="renderHotelDetails(searchData)"
    />
  </div>
</template>

<script>
import HotelSearchForm from '@/components/hotel/HotelSearchForm.vue'
import HotelAreaInfo from '@/components/hotel/HotelAreaInfo.vue'
import HotelInfoFilter from '@/components/hotel/HotelInfoFilter.vue'
import HotelList from '@/components/hotel/HotelList.vue'
import qs from 'querystring'

export default {
  name: 'Hotel',
  components: {
    HotelSearchForm,
    HotelAreaInfo,
    HotelInfoFilter,
    HotelList
  },
  data () {
    return {
      cityInfo: {
        scenics: []
      },
      hotelInfos: []
    }
  },
  methods: {
    /**
     * 查找城市
     * @param {Object} params 参数对象
     * @param {string} params.name 城市名称
     * @returns {Promise}
     */
    getCities (params) {
      return this.$axios.get('/cities', { params }).then(res => [null, res]).catch(err => [err])
    },
    /**
     * 酒店详情
     * @param {Object} [params] 参数对象
     * @param {number} [params.id] 酒店id(酒店详情)
     * @param {number} [params.city] 城市id
     * @param {number} [params.price_in] 酒店价格
     * @param {number} [params.scenic] 景点id
     * @param {string} [params.name_contains] 名字模糊查询
     * @param {number} [params.hotellevel] 酒店星级
     * @param {number} [params.hoteltype] 酒店类型
     * @param {number} [params.hotelbrand] 酒店品牌
     * @param {number} [params.hotelasset] 酒店设施
     * @param {Date} [params.enterTime] 入店时间
     * @param {Date} [params.leftTime] 离店时间
     * @param {number} [params.person] 人数
     * @param {number} [params._limit] 条数
     * @param {string} [params._sort] 排序
     * @param {number} [params._start] 当前数据项索引
     * @returns {Promise}
     */
    getHotelDetails (params) {
      /*
      注意，由于后端需要多个相同参数的请求，需要配置一个 paramsSerializer 函数
      但是有一个问题就是会保留 undefined 和 null 的字段，需要在传入配置函数前
      对传入的参数对象进行一次属性过滤
       */
      params = JSON.parse(JSON.stringify(params)) // 排除掉 undefined 项
      const filteParams = {}
      for (let key in params) {
        if (!Array.isArray(params[key])) {
          filteParams[key] = params[key]
        } else if (Array.isArray(params[key]) && params[key].length > 0) {
          filteParams[key] = params[key]
        }
      }
      return this.$axios.get('/hotels', {
        params: filteParams,
        paramsSerializer (filteParams) {
          // qs 是 node 中的核心 querystring 模块用于序列化请求字符串
          return qs.stringify(filteParams)
        }
      }).then(res => [null, res]).catch(err => [err])
    },
    async renderCityInfo (name) {
      const [err, res] = await this.getCities({ name })

      if (err) {
        return this.$message.error('获取城市数据失败')
      }

      this.cityInfo = res.data.data[0]
    },
    // 渲染酒店信息
    async renderHotelDetails (searchData) {
      const [err, res] = await this.getHotelDetails(searchData)
      if (err) {
        return this.$message.error('获取酒店数据失败')
      }
      this.hotelInfos = res.data.data
      this.$store.commit('hotel/setTotal', res.data.total)
    },
    async handleLocation (cityName) {
      await this.renderCityInfo(cityName)

      const cityId = this.cityInfo.id
      this.$store.commit('hotel/setCityId', cityId)
      this.renderHotelDetails(this.searchData)
    },
    // 搜索酒店数据
    async handleSearchHotel (cityName) {
      this.renderCityInfo(cityName)
      this.renderHotelDetails(this.searchData)
      this.$router.push({
        path: '/hotel',
        query: { cityName }
      })
    }
  },
  computed: {
    searchData () {
      return this.$store.state.hotel.searchData
    }
  }
}
</script>

<style lang="less" scoped>
.w {
  width: 1000px;
  padding: 20px 0;
  margin: 0 auto;
}
.hotel {
  .el-breadcrumb {
    margin-bottom: 20px;
    overflow: hidden;
  }
}
</style>
